using System;
using System.Collections.Generic;
using ChiWalker.Utilities;
using Styx;
using Styx.CommonBot;
using Styx.TreeSharp;

namespace ChiWalker.Spell
{
    public class NoGCDSpell : Composite
    {
        public NoGCDSpell(int id, UnitSelectionDelegate target,
            SimpleBooleanDelegate condition = null,
            bool doubleCastPrevention = false)
            : this(id, target, condition, null, doubleCastPrevention)
        {
        }

        public NoGCDSpell(int id, UnitSelectionDelegate target,
            SimpleBooleanDelegate condition = null, ActionSucceedDelegate succeedRunner = null,
            bool doubleCastPrevention = false)
            : this(id, target, null, condition, succeedRunner, doubleCastPrevention)
        {
        }

        public NoGCDSpell(int id, UnitSelectionDelegate target, string log = null,
            SimpleBooleanDelegate condition = null, ActionSucceedDelegate succeedRunner = null,
            bool doubleCastPrevention = false)
        {
            SpellId = id;
            Target = target;
            LogReason = log;
            Condition = condition;
            SucceedRunner = succeedRunner;
            DoubleCastPrevention = doubleCastPrevention;
        }

        public int SpellId { get; set; }
        public string LogReason { get; set; }
        public UnitSelectionDelegate Target { get; set; }
        public SimpleBooleanDelegate Condition { get; set; }
        public ActionSucceedDelegate SucceedRunner { get; set; }
        public bool DoubleCastPrevention { get; set; }

        public override RunStatus Tick(object context)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (!WaitFor.SpellGcd.IsFinished)
                    return RunStatus.Success;

                if (DoubleCastPrevention && WaitFor.LastCastSpell == SpellId && WaitFor.LastTarget == Target)
                {
                    Logger.WriteVerbose("Prevented double cast of {0}", SpellId);
                    return RunStatus.Failure;
                }


                if (!SpellManager.HasSpell(SpellId))
                    return RunStatus.Failure;

                if (Target(context) == null)
                    return RunStatus.Failure;

                if (!Target(context).IsFriendly && !Target(context).PvpFlagged && Target(context).IsPlayer)
                {
                    Logger.Write("Blacklisting {0} as we cant attack it", Target(context).Name);
                    if (StyxWoW.Me.CurrentTarget == Target(context))
                        StyxWoW.Me.ClearTarget();
                    Blacklist.Add(Target(context).Guid, BlacklistFlags.Combat, TimeSpan.FromMinutes(10));
                }

                if (Condition != null && !Condition(context))
                    return RunStatus.Failure;

                if (!SpellManager.CanCast(SpellId, Target(context), true))
                    return RunStatus.Failure;


                Logger.Write(LogReason ?? "Casting {0} on {1}", SpellId, Target(context).Name);
                bool castSucces = SpellManager.Cast(SpellId, Target(context));

                WaitFor.SpellGcd.Reset();

                WaitFor.LastCastSpell = SpellId;
                WaitFor.LastTarget = Target;

                if (!castSucces)
                    return RunStatus.Failure;

                if (SucceedRunner != null)
                    SucceedRunner(context);

                return RunStatus.Failure;
            }
        }

        protected override IEnumerable<RunStatus> Execute(object context)
        {
            yield return Tick(context);
        }
    }
}